home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-10-06 | 10.4 KB | 393 lines | [TEXT/CWIE] |
- ///--------------------------------------------------------------------------------------
- // BlitPixieRLECollision
- //
- // based on original code by Mick Foley <mick@emf.net>
- // from the book "Tricks of the Mac Game Programming Gurus" by Hayden Books.
- //
- // Written by Anders F Björklund <afb@algonet.se>
- // © 1998-99 afb.
- ///--------------------------------------------------------------------------------------
-
- #ifndef GENERATINGASM // do not include for asm file generation
-
- #ifdef macintosh
-
- #include <Types.h>
- #include <Errors.h>
- #include <Memory.h>
-
- #else
-
- #include <stdlib.h>
-
- #endif
-
- #ifndef __BLITPIXIE__
- #include "BlitPixieHeader.h"
- #endif
-
- // Number of bytes before starting a fill run
- #define kMinimumFillRun 32
-
- // flags for compiler pixelrun state
- enum RunFlags
- {
- kRunNone = 0,
- kRunSkip,
- kRunDraw,
- kRunFill
- };
-
- #define ALIGN_PTR(p) ( (-((long) p)) & 3)
-
- #ifdef macintosh
-
- #define RESULT_TYPE OSErr
- #define ALLOC NewHandle
- #define TEMP_TYPE Handle
- #define RETURN_TYPE TokenDataHdl
-
- #else
-
- #define RESULT_TYPE int
- #define ALLOC malloc
- #define TEMP_TYPE void*
- #define RETURN_TYPE TokenDataPtr
-
- #define noErr 0
- #define paramErr -50
- #define memFullErr -28
-
- #endif
-
- ///--------------------------------------------------------------------------------------
- // RLEParsePixels - create RLE tokens
- ///--------------------------------------------------------------------------------------
-
- RESULT_TYPE BlitPixieRLEParsePixels(
- unsigned char *srcStartAddrP,
- unsigned char *maskStartAddrP,
- unsigned long rowBytes,
- unsigned short numBytesPerRow,
- unsigned short numberOfScanLines,
- unsigned short depth,
- RETURN_TYPE* newPixCode)
- {
- RESULT_TYPE err = noErr;
- unsigned long newSize;
- TEMP_TYPE tempPixCodeH;
-
- unsigned char runFlag;
-
- unsigned char *lineStartPtr; // where is the token for the start of the current line
- unsigned char *runTokenPtr; // where is the token for the current run
- unsigned char *dataPtr; // points to where we are saving/encoding the data
-
- unsigned char *sourcePtr; // points to the graphics data we are saving in our image
- unsigned char *maskPtr; // points to whichever mask we are currently encoding
- unsigned char *sourceStartPtr; // points to the beginning of a source row.
- unsigned char *maskStartPtr; // points to the beginning of a source row.
-
- unsigned long xCounter; // a counter to scan the shape horizontally
- unsigned long yCounter; // a counter to scan the shape vertically
-
- unsigned long thisPixel;
- unsigned long maskPixel;
- unsigned long lastPixel;
- unsigned long advance;
-
- unsigned long runCounter; // how long is the current run?
- unsigned long sameCounter; // how many similar pixels in a row ?
-
- Boolean useDrawSpans = BLITPIXIE_USE_DRAW_SPANS;
-
- *newPixCode = NULL;
-
- if ( depth != 8 && depth != 16 && depth != 32 )
- return paramErr;
- if ( numBytesPerRow <= 0 || numberOfScanLines <= 0 )
- return paramErr;
-
- newSize = 2 * sizeof(TokenDataType) * ( (long) numberOfScanLines * (long) numBytesPerRow) +
- sizeof(TokenDataType) * numberOfScanLines + sizeof(TokenDataType);
-
- advance = depth >> 3;
-
- tempPixCodeH = ALLOC(newSize);
- if (tempPixCodeH != NULL)
- {
-
- #if macintosh
-
- // lock the handle and get the pointer
- HLock ((Handle) tempPixCodeH);
- dataPtr = (unsigned char *) ( *tempPixCodeH );
-
- #else
- // just get the pointer
- dataPtr = (unsigned char *) ( tempPixCodeH );
-
- #endif
-
- sourceStartPtr = ( unsigned char * ) srcStartAddrP;
- maskStartPtr = ( unsigned char * ) maskStartAddrP;
-
- // scan the shape row by row
- for( yCounter = 0; yCounter < numberOfScanLines; yCounter++ )
- {
- // we need to store where this line starts so we can fill in the lineStart token later.
- lineStartPtr = dataPtr;
- dataPtr += sizeof( TokenDataType );
-
- // at the beginning of each row we are not in any run
- runFlag = kRunNone;
- runCounter = 0;
- sameCounter = 0;
-
- // move to the start of the row
- sourcePtr = sourceStartPtr;
- maskPtr = maskStartPtr;
-
- // scan each pixel of this row
- for( xCounter = 0; xCounter < numBytesPerRow; xCounter += advance)
- {
- // check the mask to see if this is a clear pixel or not.
- switch ( depth )
- {
- case 8: maskPixel = *((unsigned char *) maskPtr); break;
- case 16: maskPixel = *((unsigned short *) maskPtr); break;
- case 32: maskPixel = *((unsigned long *) maskPtr); break;
- }
-
- if ( maskPixel != 0)
- { // pixel is transparent
-
- sameCounter = 0;
-
- switch ( runFlag )
- {
- case kRunSkip:
- // continue skip run
- runCounter += advance;
- break;
- case kRunDraw:
- // end draw run
- *((TokenDataType *) runTokenPtr) = ( kDrawPixelsToken << kTokenShift ) + runCounter;
- dataPtr += ALIGN_PTR(dataPtr);
-
- // start skip run
- runTokenPtr = dataPtr;
- dataPtr += sizeof(TokenDataType);
- runFlag = kRunSkip;
- runCounter = advance;
-
- break;
- case kRunFill:
- // end fill run
- *((TokenDataType *) runTokenPtr) = ( kSingleColorToken << kTokenShift ) + runCounter;
- runTokenPtr += sizeof(TokenDataType);
- if ( depth < 16 ) lastPixel |= lastPixel << 8;
- if ( depth < 32 ) lastPixel |= lastPixel << 16;
- *( ( unsigned long * )runTokenPtr ) = lastPixel;
- runTokenPtr += sizeof(unsigned long);
-
- // start skip run
- runTokenPtr = dataPtr;
- dataPtr += sizeof(TokenDataType);
- runFlag = kRunSkip;
- runCounter = advance;
- break;
- case kRunNone:
- // start skip run
- runTokenPtr = dataPtr;
- dataPtr += sizeof(TokenDataType);
- runFlag = kRunSkip;
- runCounter = advance;
- break;
- }
- }
- else // pixel is masked
- {
- switch ( depth )
- {
- case 8: thisPixel = *((unsigned char *) sourcePtr); break;
- case 16: thisPixel = *((unsigned short *) sourcePtr); break;
- case 32: thisPixel = *((unsigned long *) sourcePtr); break;
- }
-
- if ( useDrawSpans && (thisPixel == lastPixel) && (sameCounter + advance >= kMinimumFillRun) )
- {
- switch (runFlag)
- {
- case kRunFill:
- // continue fill run
- runCounter += advance;
- break;
- case kRunDraw:
- if ( runCounter > sameCounter )
- {
- // end draw run
- *((TokenDataType *) runTokenPtr) =
- ( kDrawPixelsToken << kTokenShift ) + (runCounter - sameCounter);
-
- dataPtr -= sameCounter;
- dataPtr += ALIGN_PTR(dataPtr);
- }
- else
- {
- // delete draw run
- dataPtr = runTokenPtr;
- }
-
- // start fill run
- runTokenPtr = dataPtr;
- dataPtr += sizeof(TokenDataType) + sizeof(unsigned long);
- runFlag = kRunFill;
- runCounter = sameCounter + advance;
- break;
- }
- }
- else
- {
- if ( sameCounter > 0 && thisPixel == lastPixel )
- sameCounter += advance;
- else
- sameCounter = advance;
-
- switch ( runFlag )
- {
- case kRunDraw:
- // continue draw run
- runCounter += advance;
- break;
- case kRunFill:
- // end fill run
- *((TokenDataType *) runTokenPtr) = ( kSingleColorToken << kTokenShift ) + runCounter;
- runTokenPtr += sizeof(TokenDataType);
-
- if ( depth < 16 ) lastPixel |= lastPixel << 8;
- if ( depth < 32 ) lastPixel |= lastPixel << 16;
- *( ( unsigned long * )runTokenPtr ) = lastPixel;
- runTokenPtr += sizeof(unsigned long);
-
- // start draw run
- runTokenPtr = dataPtr;
- dataPtr += sizeof(TokenDataType);
- runFlag = kRunDraw;
- runCounter = advance;
- break;
- case kRunSkip:
- // end skip run
- *((TokenDataType *) runTokenPtr) = ( kSkipPixelsToken << kTokenShift ) + runCounter;
-
- // start draw run
- runTokenPtr = dataPtr;
- dataPtr += sizeof(TokenDataType);
- runFlag = kRunDraw;
- runCounter = advance;
- break;
- case kRunNone:
- // start draw run
- runTokenPtr = dataPtr;
- dataPtr += sizeof(TokenDataType);
- runFlag = kRunDraw;
- runCounter = advance;
- break;
- }
-
- // copy the pixel
- switch ( depth )
- {
- case 8: *((unsigned char *) dataPtr) = thisPixel; dataPtr += 1; break;
- case 16: *((unsigned short *) dataPtr) = thisPixel; dataPtr += 2; break;
- case 32: *((unsigned long *) dataPtr) = thisPixel; dataPtr += 4; break;
- }
-
- lastPixel = thisPixel;
- }
- }
-
- // move to the next pixel
- sourcePtr += advance;
- maskPtr += advance;
- }
-
- // if we're finishing up a draw/fill run, we need to write out the final data.
- switch ( runFlag )
- {
- case kRunSkip:
- // delete the skip run
- dataPtr = runTokenPtr;
- break;
- case kRunDraw:
- // create the draw token
- *( (TokenDataType *) runTokenPtr ) = ( kDrawPixelsToken << kTokenShift ) + runCounter;
- dataPtr += ALIGN_PTR(dataPtr);
- break;
- case kRunFill:
- // create the fill token
- *( ( TokenDataType *)runTokenPtr) = ( kSingleColorToken << kTokenShift ) + runCounter;
- runTokenPtr += sizeof(TokenDataType);
-
- if ( depth < 16 ) lastPixel |= lastPixel << 8;
- if ( depth < 32 ) lastPixel |= lastPixel << 16;
- *( ( unsigned long *) runTokenPtr) = lastPixel;
- runTokenPtr += sizeof(unsigned long);
- break;
- }
-
- // create the line start token
- *( ( TokenDataType * )lineStartPtr ) = ( kLineStartToken << kTokenShift ) +
- ( (long) dataPtr - sizeof(TokenDataType) - (long) lineStartPtr);
-
- // move the row start to the next row
- sourceStartPtr += rowBytes;
- maskStartPtr += rowBytes;
- }
-
- // create the end of shape token
- *( ( TokenDataType * )dataPtr ) = kEndShapeToken << kTokenShift;
- dataPtr += sizeof(TokenDataType);
-
- #ifdef macintosh
-
- newSize = dataPtr - (unsigned char *) (*tempPixCodeH );
-
- // Unlock the handle
- HUnlock( (Handle) tempPixCodeH );
-
- // Resize the handle to match the real size of the shape
- SetHandleSize( (Handle) tempPixCodeH, newSize );
- err = MemError();
-
- #else
-
- newSize = dataPtr - (unsigned char *) (tempPixCodeH);
-
- tempPixCodeH = realloc( tempPixCodeH, newSize );
- if ( tempPixCodeH == NULL )
- err = memFullErr;
-
- #endif
-
- if (err == noErr)
- {
- *newPixCode = (RETURN_TYPE) tempPixCodeH;
- }
- }
- else
- {
- err = memFullErr;
- }
-
- return err;
- }
-
- #endif //GENERATINGASM
-
-
-
-
-
-
-